package com.lovely602.ai.alibaba.controller.audio;


import com.alibaba.cloud.ai.dashscope.api.DashScopeAudioSpeechApi;
import com.alibaba.cloud.ai.dashscope.audio.DashScopeAudioSpeechOptions;
import com.alibaba.cloud.ai.dashscope.audio.synthesis.SpeechSynthesisModel;
import com.alibaba.cloud.ai.dashscope.audio.synthesis.SpeechSynthesisPrompt;
import com.alibaba.cloud.ai.dashscope.audio.synthesis.SpeechSynthesisResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.CountDownLatch;

/**
 * 文本转语音模型
 *
 * @author lizhixing
 */
@Slf4j
@RestController
@RequestMapping(value = "/ai/speech")
public class SpeechSynthesisController {

    private static final String AUDIO_FILE_PATH = "E:\\audio";

    private static final String AUDIO_FILE_CONTENT = """
            床前明月光，
            疑是地上霜。
            举头望明月，
            低头思故乡。
            """;

    // 文本转语音
    private final SpeechSynthesisModel speechSynthesisModel;

    public SpeechSynthesisController(SpeechSynthesisModel speechSynthesisModel) {
        this.speechSynthesisModel = speechSynthesisModel;
    }

    /**
     * 文本转语音
     */
    @GetMapping(value = "/tts")
    public void tts() {

        // 语音合成模型参数
        DashScopeAudioSpeechOptions audioSpeechOptions = DashScopeAudioSpeechOptions.builder()
                .model(DashScopeAudioSpeechApi.AudioSpeechModel.SAM_BERT_ZHICHU_V1.getValue())
                .speed(1.0f)
                .volume(10)
                .build();

        // 语音合成提示信息
        SpeechSynthesisPrompt prompt = new SpeechSynthesisPrompt(AUDIO_FILE_CONTENT, audioSpeechOptions);

        // 调用语音合成模型
        SpeechSynthesisResponse response = speechSynthesisModel.call(prompt);

        File file = new File(AUDIO_FILE_PATH + "/output.mp3");
        try (FileOutputStream fos = new FileOutputStream(file)) {

            ByteBuffer byteBuffer = response.getResult().getOutput().getAudio();
            fos.write(byteBuffer.array());
        } catch (IOException e) {
            log.error("write file error: ", e);
        }
    }

    /**
     * 文本转语音
     */
    @GetMapping("/tts/stream")
    public void streamTTS() {

        Flux<SpeechSynthesisResponse> response = speechSynthesisModel.stream(
                new SpeechSynthesisPrompt(
                        AUDIO_FILE_CONTENT,
                        DashScopeAudioSpeechOptions.builder()
                                .model(DashScopeAudioSpeechApi.AudioSpeechModel.SAM_BERT_ZHITING_V1.getValue())
                                .build()
                )
        );

        CountDownLatch latch = new CountDownLatch(1);
        File file = new File(AUDIO_FILE_PATH + "/output-stream.mp3");
        try (FileOutputStream fos = new FileOutputStream(file)) {

            response.doFinally(
                    signal -> latch.countDown()
            ).subscribe(synthesisResponse -> {
                ByteBuffer byteBuffer = synthesisResponse.getResult().getOutput().getAudio();
                byte[] bytes = new byte[byteBuffer.remaining()];
                byteBuffer.get(bytes);
                try {
                    fos.write(bytes);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });

            latch.await();
        } catch (IOException | InterruptedException e) {
            throw new RuntimeException(e);
        }
    }


}
